package com.whately.core.redis;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

/**
 * boot升级到2.2
 */
@Configuration
public class WhatelyRedisConfiguration {

    @Bean
    public GenericObjectPoolConfig genericObjectPoolConfig() {
        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();

        genericObjectPoolConfig.setMaxTotal(200);
        //最大空闲数
        genericObjectPoolConfig.setMaxIdle(50);
        genericObjectPoolConfig.setMinIdle(10);
        //连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
        genericObjectPoolConfig.setBlockWhenExhausted(true);
        genericObjectPoolConfig.setMaxWaitMillis(1000);
        //在borrow一个实例时，是否提前进行alidate操作；如果为true，则得到的实例均是可用的
        genericObjectPoolConfig.setTestOnBorrow(true);
        //调用returnObject方法时，是否进行有效检查
        genericObjectPoolConfig.setTestOnReturn(true);
        //在空闲时检查有效性, 默认false
        genericObjectPoolConfig.setTestWhileIdle(false);
        //表示idle object evitor两次扫描之间要sleep的毫秒数；
        genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(30000);
        //表示一个对象至少停留在idle状态的最短时间，
        //然后才能被idle object evitor扫描并驱逐；这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义；
        genericObjectPoolConfig.setMinEvictableIdleTimeMillis(10000);

        return genericObjectPoolConfig;
    }

    @Bean
    @Primary
    public RedisConnectionFactory redisConnectionFactory(GenericObjectPoolConfig genericObjectPoolConfig,RedisProperties properties){
        //通过配置RedisClusterConfiguration实例来创建工厂
        //构造该对象是传入Lettuce客户端配置和redis集群配置
        //redis配置
        int dbIndex = 0;
        //redis客户端配置
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(createRedisConfiguration(dbIndex,properties));

        lettuceConnectionFactory.setDatabase(dbIndex);

        /**
         * 不能加下面这句话，否则createClient会内存溢出
         * AbstractAutowireCapableBeanFactory#invokeInitMethods ,会调用afterPropertiesSet
         */
        //lettuceConnectionFactory.afterPropertiesSet();


        return lettuceConnectionFactory;
    }


    private RedisStandaloneConfiguration createRedisConfiguration(int dbIndex,RedisProperties properties){
        RedisStandaloneConfiguration redisConfiguration = new
                RedisStandaloneConfiguration(properties.getHost(),properties.getPort());
        redisConfiguration.setDatabase(dbIndex);
        redisConfiguration.setPassword(properties.getPassword());
        return redisConfiguration;
    }

}
